/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.sarco.bwi.lib;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Timer;

/**
 *
 * @author iktsup
 */
public class Node {

    public static final String DEFAULT_CONFIG = "node.config";

    /**
     *
     */
    public static String COMMON_SPLIT = ";";

    /**
     *
     */
    public static String NODE_STATUS            = "NODE::STATUS";
    /**
     *
     */
    public static String NODE_DONE              = "NODE::DONE";
    /**
     *
     */
    public static String NODE_GOT_JOB           = "NODE::GOT::JOB";
    /**
     *
     */
    public static String NODE_OS                = "NODE::OS";

    /**
     *
     */
    public static String MASTER_SHARE_JOBS  = "MASTER::SHARE::JOBS";

    public static String MASTER_TERMINATE   = "MASTER::TERMINATE";
    /**
     *
     */
    private InputStream in;
    private OutputStream out;
    private Socket client;
    private int startFrame = 0;
    private int endFrame = 0;
    private int currFrame = 0;
    private String timeLeft = "";
    private String system = "";
    private boolean done = false;
    private int id;

    public boolean canTerminate = false;

    private boolean canStart = false;
    private Config config;
    private Timer timerMessages;

    /**
     *
     */
    public int iPercentDone = 0;

    /**
     *
     * @param config
     */
    public void init(Config config) {
        try {
            this.config = config;
            this.setClient(new Socket(this.config.getMaster(), this.config.getPort()));
            this.setIn(this.getClient().getInputStream());
            this.setOut(this.getClient().getOutputStream());

            this.setSystem(System.getProperty("os.name"));
        } catch (UnknownHostException ex) {
            
        } catch (IOException ex) {
            
        }
    }

    /**
     *
     */
    public void waitForJob() {
        while (!this.canStart) {
            System.out.println("Waiting for COMMAND!");
            try {
                String s = "";
                byte[] bIn = new byte[128] ;
                this.getIn().read(bIn);
                for (int i = 0; i < bIn.length; i++) {
                    s += (char) bIn[i];
                }
                System.out.println("Got command!");
                if (s.startsWith(Node.MASTER_SHARE_JOBS)) {
                        s = s.substring(Node.MASTER_SHARE_JOBS.length());
                        String[] frames = s.split(Node.COMMON_SPLIT);
                        this.setStartFrame(Integer.parseInt(frames[0]));
                        this.setEndFrame(Integer.parseInt(frames[1]));
                        this.canStart = true;
                    }
            } catch (IOException ex) {
                Logger.getLogger(Node.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     *
     */
    public void startJob() {
        if (this.canStart) {
            System.out.println("Starting job!");
            Blender blender = new Blender(
                     this.config.getBlenderPath(), this.config.getBlend(), this.getStartFrame(), this.getEndFrame(), this.config.getOuput(), this.config.getFormat(),
                    1, this.getClient());
            blender.render();
        }
    }

    public void initTimers() {
        ActionListener msgListener = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                waitForMessages();
            }
        };

        this.timerMessages = new Timer(1, msgListener);
        this.timerMessages.start();
    }

    public void waitForMessages() {
        try {
            String s = "";
            byte[] bIn = new byte[512];
            this.getIn().read(bIn);
            for (int y = 0; y < bIn.length; y++) {
                s += (char) bIn[y];
            }

            if (s.startsWith(Node.MASTER_TERMINATE));
                this.canTerminate = true;
        } catch (IOException ex) {
            
        }
    }

    public void cleanUp() {
        try {
            this.timerMessages.stop();
            this.getOut().close();
            this.getIn().close();
            this.getClient().close();
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

    /**
     * @return the in
     */
    public InputStream getIn() {
        return in;
    }

    /**
     * @param in the in to set
     */
    public void setIn(InputStream in) {
        this.in = in;
    }

    /**
     * @return the out
     */
    public OutputStream getOut() {
        return out;
    }

    /**
     * @param out the out to set
     */
    public void setOut(OutputStream out) {
        this.out = out;
    }

    /**
     * @return the client
     */
    public Socket getClient() {
        return client;
    }

    /**
     * @param client the client to set
     */
    public void setClient(Socket client) {
        this.client = client;
    }

    /**
     * @return the startFrame
     */
    public int getStartFrame() {
        return startFrame;
    }

    /**
     * @param startFrame the startFrame to set
     */
    public void setStartFrame(int startFrame) {
        this.startFrame = startFrame;
    }

    /**
     * @return the endFrame
     */
    public int getEndFrame() {
        return endFrame;
    }

    /**
     * @param endFrame the endFrame to set
     */
    public void setEndFrame(int endFrame) {
        this.endFrame = endFrame;
    }

    /**
     * @return the currFrame
     */
    public int getCurrFrame() {
        return currFrame;
    }

    /**
     * @param currFrame the currFrame to set
     */
    public void setCurrFrame(int currFrame) {
        this.currFrame = currFrame;
    }

    /**
     * @return the timeLeft
     */
    public String getTimeLeft() {
        return timeLeft;
    }

    /**
     * @param timeLeft the timeLeft to set
     */
    public void setTimeLeft(String timeLeft) {
        this.timeLeft = timeLeft;
    }

    /**
     * @return the system
     */
    public String getSystem() {
        return system;
    }

    /**
     * @param system the system to set
     */
    public void setSystem(String system) {
        this.system = system;
    }

    /**
     * @return the iPercentDone
     */
    public int getiPercentDone() {
        return iPercentDone;
    }

    /**
     * @param iPercentDone the iPercentDone to set
     */
    public void setiPercentDone(int iPercentDone) {
        this.iPercentDone = iPercentDone;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
